<template>
  <nav-bar :title="`${text}地址`" :back="false">
    <template v-slot:left>
      <div>
        <svg-icon name="back" @click="enterBeforePage"></svg-icon>
      </div>
    </template>
  </nav-bar>
  <div class="main">
    <van-form
      @submit="onSubmit"
      @click.stop="handleMove"
      :class="{ 'move-up': moveUp, 'move-down': !moveUp && !isDetailSearch, searchDetail: isDetailSearch }"
    >
      <div class="form">
        <van-field
          v-model="address"
          readonly
          clickable
          :is-link="false"
          input-align="left"
          :placeholder="`请选择${text}地`"
          name="address"
          @click="hanldeStartPicker"
          :rules="[{ required: true, trigger: 'onChange', message: `请选择${text}地` }]"
        >
          <template #extra>
            <div class="address-icon" @click.stop="enterAddressList">
              常用地址
              <svg-icon :name="'address'"></svg-icon>
            </div>
          </template>
        </van-field>
        <van-field
          v-model="detailAddress"
          :placeholder="`请输入${text}详细地址`"
          @click.stop
          @focus="handleAdressFocus"
          @update:model-value="handleAdressChange"
          clearable
        />
        <!-- <div v-show="!isDetailSearch"> -->
        <div v-show="!isDetailSearch">
          <van-field
            v-model="name"
            :placeholder="`请输入${text}联系人姓名`"
            :rules="[{ required: true, trigger: 'onChange', message: `请输入${text}联系人姓名` }]"
          />
          <van-field
            v-model="phone"
            type="digit"
            :placeholder="`请输入${text}人手机号`"
            :rules="[
              { required: true, trigger: 'onChange', message: `请输入${text}人手机号` },
              { validator, trigger: 'onBlur', message: '手机号有误' }
            ]"
          />
          <van-field name="checkbox" label="添加常用地址" input-align="right" class="addAddress">
            <template #input>
              <svg-icon :name="adressChecked ? 'selected2' : 'select2'" @click="handleAddAdress"></svg-icon>
            </template>
          </van-field>
          <van-button type="primary" class="button" native-type="submit">确认{{ text }}地址</van-button>
        </div>
      </div>
      <!-- </div> -->
    </van-form>
    <div class="areaList" v-show="areaSearchList.length > 0 && isDetailSearch">
      <div class="areaList-item" v-for="(item, index) in areaSearchList" :key="index" @click="selectAreaSearch(item)">
        <svg-icon name="address-location"></svg-icon>
        <div class="content">
          <div class="content-title">{{ item.title }}</div>
          <div class="addressAll">{{ item.address }}</div>
        </div>
      </div>
    </div>
    <div id="container"></div>
    <div class="mapMask" :class="moveUp ? 'addMapMask' : ''" @click="handleMask"></div>
  </div>

  <van-popup v-model:show="startPicker" position="bottom">
    <van-picker
      :columns="areaList"
      :columns-field-names="{
        text: 'name',
        value: 'id'
      }"
      @cancel="startPicker = false"
      @confirm="onStartConfirm"
    />
  </van-popup>
</template>

<script lang="ts">
import navBar from '@/components/NavBar.vue'
import { reactive, toRefs, ref, unref, onMounted, watch, onUnmounted } from 'vue'
import areaList from '@/utils/areaData'
import { useRoute, useRouter } from 'vue-router'
import { Toast } from 'vant'
import http from '@/http'
import { api } from '@/http/api'
import jsonp from 'jsonp'
import locationIcon from '@/assets/image/location.png'
import { location, debounce } from '@/utils/utils'
import store from '@/store/index'
import { Position } from '@/type'

export default {
  name: 'AddressInfo',
  components: {
    navBar
  },
  setup() {
    const validator = (val: string) => /^1(3[0-9]|5[0-3,5-9]|7[1-3,5-8]|8[0-9])\d{8}$/.test(val)

    const route = useRoute(),
      router = useRouter()
    const type = route.params.type
    const text = type === 'start' ? '装货' : '卸货'
    const addressType = type === 'start' ? 1 : 2
    const state = reactive({
      startPicker: false,
      address: '',
      addressArr: [] as any[],
      detailAddress: '',
      name: '',
      phone: '',
      type,
      adressChecked: false, //是否选中添加常用地址
      addressLatitude: '' as any, //地址纬度
      addressLongitude: '' as any, //地址经度
      moveUp: false, //判断表单上下移动方向
      isSearchLat: false, //是否通过地址查询经纬度
      oldDetailAddress: '', //缓存初始详细地址
      oldAddress: '', //缓存初始省市区
      panByFlag: true, //是否触发form动画点击事件
      positionFlag: false, //定位开关
      isDetailSearch: false, //是否地区详细POI
      areaSearchList: [] //POI检索数据
    })

    // 返回上一页
    const enterBeforePage = () => {
      router.push({
        name: 'Delivery'
      })
    }

    // 触发级联选择器
    const hanldeStartPicker = () => {
      state.moveUp ? (state.startPicker = true) : ''
      state.oldAddress = state.address
    }

    // 确认级联选择器
    const onStartConfirm = (values: any) => {
      state.startPicker = false
      state.addressArr = values.map((item: any) => {
        return { name: item.name, id: item.id }
      })
      state.address = values.map((item: any) => item.name).join('/')
      // 重置详细地址
      state.detailAddress = ''
      // 查询经纬度
      state.address !== state.oldAddress ? (state.isSearchLat = true) : ''
      state.isDetailSearch && detailSearch()
    }
    //POI检索
    const detailSearch = () => {
      var options = {
        onSearchComplete: function (results: any) {
          if (local.getStatus() == 0) {
            state.areaSearchList = results._pois
          }
        }
      }
      const local = new BMapGL.LocalSearch(map, options)
      const area = state.address.replace(/\/*/g, '') + state.detailAddress
      local.search(area)
    }
    const detailSearchDebounce = debounce(detailSearch, 1000)

    //选择POI检索地址
    const selectAreaSearch = (item: any) => {
      const address = state.address.split('/')
      let detailAddress = item.address
      address.map(item => {
        detailAddress = detailAddress.replace(item, '')
      })
      state.detailAddress = detailAddress ? detailAddress : item.title
      state.areaSearchList = []
      state.isDetailSearch = false
      state.panByFlag = true
      state.moveUp = false
      if (state.detailAddress !== state.oldDetailAddress) {
        state.isSearchLat = true
      }
    }

    // 详细地址输入框触发
    const handleAdressFocus = () => {
      if (!state.address) {
        Toast('请先选择省市区')
        return
      }
      state.oldDetailAddress = state.detailAddress
      state.isDetailSearch = true
      detailSearch()
    }
    const handleAdressChange = () => {
      detailSearchDebounce()
    }

    // 确认装卸货地址
    const onSubmit = () => {
      if (!state.detailAddress) {
        Toast('请输入详细地址')
        return
      }
      router.push({ name: 'Delivery', params: { addressInfo: JSON.stringify(unref(state)) } })
    }

    // 添加常用地址
    const handleAddAdress = () => {
      if (state.adressChecked || !state.address || !state.detailAddress || !state.name || !state.phone) return
      const param = {
        provinceName: state.addressArr[0].name,
        provinceCode: state.addressArr[0].id,
        cityName: state.addressArr[1].name,
        cityCode: state.addressArr[1].id,
        countyName: state.addressArr[2].name,
        countyCode: state.addressArr[2].id,
        detailAddress: state.detailAddress,
        addressLatitude: state.addressLatitude,
        addressLongitude: state.addressLongitude,
        addressType,
        consigneeConsignor: state.name,
        consigneeConsignorPhone: state.phone
      }
      http<string>({
        url: api.addTransportAdress,
        method: 'post',
        data: param
      }).then(() => {
        state.adressChecked = true
      })
    }

    // 从常用地址返回
    const usedAdressBack = () => {
      const addressOption = JSON.parse(route.params.addressOption as string)
      // 省市区
      state.address = addressOption.provinceName + '/' + addressOption.cityName + '/' + addressOption.countyName
      // 详细地址
      state.detailAddress = addressOption.detailAddress
      // 城市编码
      state.addressArr = [
        { name: addressOption.provinceName, id: addressOption.provinceCode },
        { name: addressOption.cityName, id: addressOption.cityCode },
        { name: addressOption.countyName, id: addressOption.countyCode }
      ]
      // 缓存经纬度
      state.addressLatitude = addressOption.addressLatitude
      state.addressLongitude = addressOption.addressLongitude
      // 缓存联系人信息
      state.name = addressOption.consigneeConsignor
      state.phone = addressOption.consigneeConsignorPhone
      // 选中项
      state.adressChecked = true
    }

    watch(
      [() => state.isSearchLat, () => state.address, () => state.detailAddress, () => state.name, () => state.phone],
      ([isSearchLat]) => {
        // 取消选中项
        state.adressChecked = false
        // 更新经纬度
        if (isSearchLat) {
          state.isSearchLat = false
          const searchAddress = state.address.replace(/\/*/g, '') + state.detailAddress
          geoCoordinate(searchAddress)
        }
      }
    )

    const initData = () => {
      if (route.params && route.params.adderssInfo && route.params.adderssInfo !== '{}') {
        // 从发货进入
        const adderssInfo = JSON.parse(route.params.adderssInfo as string)
        Object.assign(state, { ...adderssInfo })
        // 展开表单
        state.moveUp = true
      } else if (route.params && route.params.addressOption) {
        // 从常用地址返回
        usedAdressBack()
        // 展开表单
        state.moveUp = true
      } else {
        // 收缩表单
        state.moveUp = false
      }
    }

    // 地图初始化
    let map: any
    const initMap = () => {
      map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 14) // 初始化地图,设置中心点坐标和地图级别

      if ((route.params?.adderssInfo && route.params.adderssInfo !== '{}') || route.params?.addressOption) {
        if (!state.addressLatitude || !state.addressLongitude) {
          state.addressLatitude = '39.915129'
          state.addressLongitude = '116.403963'
        }
        markerFn(state.addressLatitude, state.addressLongitude)
        map.panBy(0, -140)
        state.panByFlag = false
      } else {
        // 定位
        getLocation()
      }

      // 点击地图事件
      map.addEventListener('click', function (e: any) {
        const lat = e.latlng.lat
        const lng = e.latlng.lng
        markerFn(lat, lng)
        // 查询编码和填充内容
        geoCoding(lat, lng)
        // 缓存经纬度
        state.addressLatitude = lat
        state.addressLongitude = lng
      })
    }

    // 创建点标记
    const markerFn = (lat: string | number, lng: string | number) => {
      // 清除覆盖物
      map.clearOverlays()

      // 创建定位图标
      const myIcon = new BMapGL.Icon(locationIcon, new BMapGL.Size(23, 27))
      // 创建Marker标注
      var pt = new BMapGL.Point(lng, lat)
      var marker = new BMapGL.Marker(pt, {
        icon: myIcon
      })
      // 在地图上添加点标记
      map.addOverlay(marker)

      // 设置地图中心点
      var point = new BMapGL.Point(lng, lat)
      map.setCenter(point)
    }

    //获取当前定位
    const getLocation = () => {
      location(true).then((position: Position) => {
        if (position.status == 0) {
          markerFn(position.latitude, position.longitude)
          // 查询编码和填充内容
          geoCoding(position.latitude, position.longitude)
          // 缓存经纬度
          state.addressLatitude = position.latitude
          state.addressLongitude = position.longitude
        } else {
          switch (position.status) {
            case 6:
              // jsBridge.jsCallNative(NATIVE_TYPE.SET_LOCATION_PERMISSION, {})
              Toast('未获取定位权限，请在设置中授权定位权限！')
              break
            case 8:
              Toast('定位请求超时')
              break
            default:
              Toast('您的定位请求出错')
              break
          }
        }
      })
    }

    //通过经纬度反查城市编码
    const geoCoding = (lat: string | number, lng: string | number) => {
      jsonp(
        `https://api.map.baidu.com/reverse_geocoding/v3/?ak=ExH04MojWSOMytGqihygzl6hxpHws97A&output=json&coordtype=wgs84ll&location=${lat},${lng}`,
        null,
        (err: any, data: any) => {
          if (err) {
            Toast('请开启GPS,保持网络信号通畅')
          } else {
            const addressComponent = data?.result?.addressComponent
            // 省市区
            state.address = addressComponent.province + '/' + addressComponent.city + '/' + addressComponent.district
            // 详细地址
            state.detailAddress = addressComponent.street + addressComponent.street_number
            // 城市编码
            const provinceCode = addressComponent.adcode.slice(0, 2) + '0000'
            const cityCode = addressComponent.adcode.slice(0, 4) + '00'
            state.addressArr = [
              { name: addressComponent.province, id: provinceCode },
              { name: addressComponent.city, id: cityCode },
              { name: addressComponent.district, id: addressComponent.adcode }
            ]
          }
        }
      )
    }

    //通过地址查经纬度
    const geoCoordinate = (address: string) => {
      jsonp(
        `https://api.map.baidu.com/geocoding/v3/?ak=ExH04MojWSOMytGqihygzl6hxpHws97A&output=json&address=${address}`,
        null,
        (err: any, data: any) => {
          if (err) {
            Toast('请开启GPS,保持网络信号通畅')
          } else {
            const lat = data.result.location.lat
            const lng = data.result.location.lng
            markerFn(lat, lng)
            // 缓存经纬度
            state.addressLatitude = lat
            state.addressLongitude = lng
          }
        }
      )
    }

    // 点击表单上下移动画
    const handleMove = () => {
      if (!state.panByFlag) return
      state.moveUp = true
      map.panBy(0, -140)
      state.panByFlag = false
    }

    // 点击常用地址进入地址页
    const enterAddressList = () => {
      if (!state.moveUp) {
        state.moveUp = true
        map.panBy(0, -140)
        state.panByFlag = false
        return
      }

      router.push({
        name: 'AddressList',
        params: { type, addressInfo: JSON.stringify(unref(state)) }
      })
    }

    //点击遮罩
    const handleMask = () => {
      // 表单下移
      state.moveUp = false
      // 偏移开关取反
      state.panByFlag = true
      map.panBy(0, 140)
    }

    onMounted(() => {
      initData()
      // 创建Map实例
      map = new BMapGL.Map('container')
      initMap()
    })

    onUnmounted(() => {
      map.destroy()
      map = null
    })

    return {
      ...toRefs(state),
      areaList,
      text,
      validator,
      onStartConfirm,
      onSubmit,
      enterAddressList,
      handleAddAdress,
      enterBeforePage,
      handleAdressFocus,
      hanldeStartPicker,
      handleMove,
      handleMask,
      selectAreaSearch,
      handleAdressChange
    }
  }
}
</script>

<style lang="scss" scoped>
@import '@/style/variables.scss';
@import '@/style/mixins.scss';
.main {
  width: 100%;
  height: $main-min-height;
  position: relative;
  overflow: hidden;
}
::v-deep(.van-form) {
  z-index: 10;
  position: absolute;
  bottom: 0px;
  left: 12px;
  right: 12px;
  background: #ffffff;
  border-radius: 15px 15px 0 0;
  overflow: hidden;
  padding: 10px 10px 15px;
  box-sizing: border-box;
}

.searchDetail {
  top: 9px;
  height: 110px;
  border-radius: 8px;
  overflow: hidden;
}
.areaList {
  position: absolute;
  top: 130px;
  left: 12px;
  right: 12px;
  bottom: 4px;
  max-height: calc(100% - 130px);
  overflow-y: auto;
  background: #fff;
  border-radius: 8px;
  padding: 0 12px;
  box-sizing: border-box;
  z-index: 100;
  &-item {
    width: 100%;
    height: 67px;
    padding-top: 15px;
    padding-left: 2px;
    box-sizing: border-box;
    display: flex;
    position: relative;
    &::after {
      @include px-1;
    }
    .svg-icon {
      width: 18px;
      height: 18px;
      margin-right: 2px;
    }
    .content {
      flex: 1;
      .addressAll {
        margin-top: 5px;
        font-size: 12px;
        color: $color-text-regular;
      }
    }
  }
}

.move-up {
  // animation: up-animation 0.2s ease forwards;
  max-height: 350px;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}

.move-down {
  // animation: down-animation 0.2s ease forwards;
  max-height: 110px;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}

@keyframes up-animation {
  0% {
    bottom: -220px;
  }
  100% {
    bottom: 0;
  }
}
@keyframes down-animation {
  0% {
    bottom: 0;
  }
  100% {
    bottom: -220px;
  }
}

.button {
  width: 100%;
  height: 44px;
  border-radius: 22px;
  margin-top: 15px;
  background: linear-gradient(125deg, #74cdff 0%, #409eff 100%);
}

.addAddress {
  .svg-icon {
    width: 16px;
    height: 16px;
  }
}

.address-icon {
  height: 50px;
  line-height: 50px;
  color: #575c72;
  .svg-icon {
    width: 22px;
    height: 22px;
  }
}

::v-deep(.van-cell) {
  padding: 10px;
  height: 50px;
  display: flex;
  align-items: center;
}
::v-deep(.van-field__control::-webkit-input-placeholder) {
  font-size: 14px;
  color: $color-text-secondary;
}
::v-deep(.van-icon) {
  color: $color-text-regular;
  font-size: 12px;
}
#container {
  width: 100%;
  height: 100%;
}
// 地图透明遮罩
.mapMask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
}
.addMapMask {
  z-index: 9;
}

:deep(.anchorBL) {
  display: none;
}
</style>
